package org.videopractice.media;

import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.view.Surface;

import org.videopractice.common.FileUtils;
import org.videopractice.common.Logger;
import org.videopractice.network.message.request.LiveDataRequest;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Media解码器
 */
public class MediaDecode  implements Runnable {

    private Surface surface;
    private Context context;

    private MediaCodec mediaCodec;

    private static final LinkedBlockingQueue<LiveDataRequest> dataPackageQueue = new LinkedBlockingQueue<>();

    public static void add(LiveDataRequest liveDataRequest) {
        dataPackageQueue.add(liveDataRequest);
    }

    public MediaDecode(Context context, Surface surface) {
        this.surface = surface;
        this.context = context;
    }

    public void play(int width, int height) {
        try {
            // 创建解码类型的编解码器
            mediaCodec = MediaCodec.createDecoderByType("video/avc");

            // 定义编解码起配置信息，  (解码格式 h264, 宽, 高)
            MediaFormat mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height);
//            mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 400_000);
            mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
//            mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2);

            /** 格式配置信息（必填）, 表层用于展示选填, 加密方式（选填）, 作用标记（这里是用来解码）*/
            mediaCodec.configure(mediaFormat, surface, null, 0);

        } catch (IOException e) {
            e.printStackTrace();
        }

        mediaCodec.start();
        new Thread(this).start();
    }

    @Override
    public void run() {

        try {



            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); // 出参

            while (true) {

                byte[] videoBuff = dataPackageQueue.take().dataPackage;
                Logger.i("videoBuff ================" + FileUtils.writeFileToString(videoBuff));

                int startIndex = 0, endIndex = videoBuff.length;

                if(endIndex <= 0 || startIndex >= endIndex - 4) {
                    break;
                }

                // 查找空闲输入缓存buffer, 如果存在则返回索引(0~15),否则返回 -1
                int inputIndex = mediaCodec.dequeueInputBuffer(10000); // 10毫秒， us是微妙的意思
                if(inputIndex >= 0) {
                    // 拿到缓存容器buffer
                    ByteBuffer byteBuffer = mediaCodec.getInputBuffer(inputIndex);
//                    // 获得容器后，将需要解码的h264编码内容提交到缓存，再由DSP硬件芯片解码。由于是硬件缓存容量极小，需要处理H264文件，一帧一帧解码。
//                    int nextIndex = findFrameIndexByBuff(videoBuff, startIndex + 2);
//                    // 将查找到的一帧索引放到buffer中去
//                    byteBuffer.put(videoBuff, startIndex, nextIndex - startIndex);


                    byteBuffer.put(videoBuff, startIndex, endIndex);
                    // 通知dsp芯片H264数据以存放入缓存需要你开始解码
//                    mediaCodec.queueInputBuffer(inputIndex, 0, nextIndex - startIndex, 0, 0);
                    mediaCodec.queueInputBuffer(inputIndex, 0, endIndex, 0, 0);
                    // 交换索引位置
//                    startIndex = nextIndex;
                } else {
                    continue;
                }

                // 取出解码数据
                int outputIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000); // 10毫秒， us是微妙的意思
                if(outputIndex >= 0) {
//                // 取出解码好的buffer数据:YUV数据
//                ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputIndex);

                    mediaCodec.releaseOutputBuffer(outputIndex, true);
                }

//                try {
//                    Thread.sleep(1000 / 25);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private int findFrameIndexByBuff(byte[] videoBuff, int startIndex) {
        for (int index = startIndex; index < videoBuff.length - 4; index++) {
            if(videoBuff[index] == 0x00 && videoBuff[index + 1] == 0x00 && videoBuff[index + 2] == 0x00 && videoBuff[index + 3] == 0x01
                    || videoBuff[index] == 0x00 && videoBuff[index + 1] == 0x00 && videoBuff[index + 2] == 0x01) {
                return index;
            }
        }
        return -1;
    }

} 
